package com.reactnativestudy.activity;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;

import androidx.annotation.Nullable;

import com.facebook.infer.annotation.Assertions;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactDelegate;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.modules.core.PermissionListener;
import com.reactnativestudy.utils.Utils;

public class MyReactActivityDelegate  {

    private static final String TAG = "MyReactActivityDelegate";

    private @Nullable
    Activity mActivity;
    private final @Nullable
    String mMainComponentName;

    private @Nullable
    PermissionListener mPermissionListener;
    private @Nullable
    Callback mPermissionsCallback;
    private ReactDelegate mReactDelegate;


    public MyReactActivityDelegate(Activity activity, @Nullable String mainComponentName) {
        mActivity = activity;
        mMainComponentName = mainComponentName;

    }

    public MyReactActivityDelegate(ReactActivity activity, @Nullable String mainComponentName) {
        mActivity = activity;
        mMainComponentName = mainComponentName;
    }

    protected @Nullable
    Bundle getLaunchOptions() {
        return null;
    }

    public  ReactRootView getReactRootView(){
        return  mReactDelegate.getReactRootView();
    }
    protected ReactRootView createRootView() {
        return new ReactRootView(getContext());
    }

    /**
     * Get the {@link ReactNativeHost} used by this app. By default, assumes {@link
     * Activity#getApplication()} is an instance of {@link ReactApplication} and calls {@link
     * ReactApplication#getReactNativeHost()}. Override this method if your application class does not
     * implement {@code ReactApplication} or you simply have a different mechanism for storing a
     * {@code ReactNativeHost}, e.g. as a static field somewhere.
     */
    protected ReactNativeHost getReactNativeHost() {
        return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
    }

    public ReactInstanceManager getReactInstanceManager() {
        return mReactDelegate.getReactInstanceManager();
    }

    public String getMainComponentName() {
        return mMainComponentName;
    }

    protected void onCreate(Bundle savedInstanceState) {
        String mainComponentName = getMainComponentName();
        ReactInstanceManager manager = getReactNativeHost().getReactInstanceManager();

        mReactDelegate =
                new ReactDelegate(
                        getPlainActivity(), getReactNativeHost(), mainComponentName, getLaunchOptions()) {
                    @Override
                    protected ReactRootView createRootView() {
                        return MyReactActivityDelegate.this.createRootView();
                    }
                };
        if (manager.hasStartedCreatingInitialContext()) {
            if (mMainComponentName != null) {
                loadApp(mainComponentName);
            }
        } else {
            Log.v(TAG, "before: "+ System.currentTimeMillis()+"");
            manager.addReactInstanceEventListener(context -> {

                Log.v(TAG, "after: "+ System.currentTimeMillis()+"");
                CatalystInstance instance = context.getCatalystInstance();
////            String entry = Utils.getItem(getApplicationContext(), "entry");
//
//                ReactBundle bundle = ReactBundle.toObject(entry);
                String s = Utils.getCachePath(getContext()) + "/bbbbbb/";
                instance.loadScriptFromFile(s + "app.android.js", s, false);
                if (mainComponentName != null) {
                    loadApp(mainComponentName);
                }

            });
        }


        manager.createReactContextInBackground();

    }

    protected void loadApp(String appKey) {
        Log.v(TAG, "loadApp: " +System.currentTimeMillis());
        mReactDelegate.loadApp(appKey);
        Log.v(TAG, "loadApped: " +System.currentTimeMillis());
        getPlainActivity().setContentView(mReactDelegate.getReactRootView());
    }

    protected void onPause() {
        mReactDelegate.onHostPause();
    }

    protected void onResume() {
        mReactDelegate.onHostResume();

        if (mPermissionsCallback != null) {
            mPermissionsCallback.invoke();
            mPermissionsCallback = null;
        }
    }

    protected void onDestroy() {
        mReactDelegate.onHostDestroy();
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        mReactDelegate.onActivityResult(requestCode, resultCode, data, true);
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (getReactNativeHost().hasInstance()
                && getReactNativeHost().getUseDeveloperSupport()
                && keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
            event.startTracking();
            return true;
        }
        return false;
    }

    public boolean onKeyUp(int keyCode, KeyEvent event) {
        return mReactDelegate.shouldShowDevMenuOrReload(keyCode, event);
    }

    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        if (getReactNativeHost().hasInstance()
                && getReactNativeHost().getUseDeveloperSupport()
                && keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
            getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
            return true;
        }
        return false;
    }

    public boolean onBackPressed() {
        return mReactDelegate.onBackPressed();
    }

    public boolean onNewIntent(Intent intent) {
        if (getReactNativeHost().hasInstance()) {
            getReactNativeHost().getReactInstanceManager().onNewIntent(intent);
            return true;
        }
        return false;
    }

    public void onWindowFocusChanged(boolean hasFocus) {
        if (getReactNativeHost().hasInstance()) {
            getReactNativeHost().getReactInstanceManager().onWindowFocusChange(hasFocus);
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    public void requestPermissions(
            String[] permissions, int requestCode, PermissionListener listener) {
        mPermissionListener = listener;
        getPlainActivity().requestPermissions(permissions, requestCode);
    }

    public void onRequestPermissionsResult(
            final int requestCode, final String[] permissions, final int[] grantResults) {
        mPermissionsCallback =
                new Callback() {
                    @Override
                    public void invoke(Object... args) {
                        if (mPermissionListener != null
                                && mPermissionListener.onRequestPermissionsResult(
                                requestCode, permissions, grantResults)) {
                            mPermissionListener = null;
                        }
                    }
                };
    }

    protected void setContext(Activity activity) {
       this.mActivity = activity;
    }


    protected Context getContext() {
        return Assertions.assertNotNull(mActivity);
    }

    protected Activity getPlainActivity() {
        return ((Activity) getContext());
    }
}
